#include "Rust3D.h"
#include <iostream>
#include <vector>
#include <cstdlib>

Rust3D* daWindow;
Camera* cam;
std::vector<MeshObject*> spheres;
MeshObject* groundQuad;
MeshObject* bowl;
void buildPyramid()
{

    //for (int i = 0; i < 10; i++)
    //{
        MeshObject* temp = new MeshObject("sphere.obj", SPHERE);
        temp->pos = Vertex3D(double(rand() % 20) - 10, 2.0, double(rand() % 20) - 10);
        temp->setRadius(1.0);
        spheres.push_back(temp);
    //}

    bowl = new MeshObject("bowl.obj", TRIANGLES);
    bowl->pos = Vertex3D(0, -25, 0);


    std::vector<ColorTriangle> jkl;

    //bottom
    ColorTriangle q(Vertex3D(-20.0, -5.0, -20.0), Vertex3D(20.0, -20.0, -20.0), Vertex3D(20.0, -20.0, 20.0), ColorVertex(1.0, 1.0, 1.0), ColorVertex(1.0, 1.0, 1.0), ColorVertex(1.0, 1.0, 1.0));
    jkl.push_back(q);

    ColorTriangle w(Vertex3D(20.0, -20.0, 20.0), Vertex3D(-20.0, -20.0, 20.0), Vertex3D(-20.0, -5.0, -20.0), ColorVertex(1.0, 1.0, 1.0), ColorVertex(1.0, 1.0, 1.0), ColorVertex(1.0, 1.0, 1.0));
    jkl.push_back(w);

    //back

    ColorTriangle t(Vertex3D(-20.0, 20.0, -20.0), Vertex3D(20.0, 20.0, -20.0), Vertex3D(20.0, -20.0, -20.0), ColorVertex(1.0, 0.0, 1.0), ColorVertex(1.0, 0.0, 1.0), ColorVertex(1.0, 0.0, 1.0));
    jkl.push_back(t);
    ColorTriangle y(Vertex3D(20.0, -20.0, -20.0), Vertex3D(-20.0, -20.0, -20.0), Vertex3D(-20.0, 20.0, -20.0), ColorVertex(1.0, 0.0, 1.0), ColorVertex(1.0, 0.0, 1.0), ColorVertex(1.0, 0.0, 1.0));
    jkl.push_back(y);
    groundQuad = new MeshObject(jkl);
    groundQuad->setPhysics(TRIANGLES);
}


/* Here goes our drawing code */
int drawGLScene(void)
{
    daWindow->resetScene();

    cam->draw();
    //groundQuad->draw();
    bowl->draw();
    //for (int i = 0; i< 10; i++)
    //{
            spheres[0]->draw();
    //}

    daWindow->flipBuffers();

    cam->update();
    //for (int i = 0; i< 10; i++)
    //{
            spheres[0]->update();
    //}
    groundQuad->update();
    //bowl->update();

    //Grabbity
    //for (int i = 0; i< 10; i++)
    //{
        spheres[0]->vPos.Sety(spheres[0]->vPos.Gety()-0.001);
    //}
    //"ground" collision;
    /*for (int i = 0; i< 10; i++)
    {
        for (int j = i+1; j < 10; j++)
        {
            spheres[i]->collide(spheres[j]);
        }
    }*/
    //for (int i = 0; i < 10; i ++)
    //{
        bowl->collide(spheres[0]);
        //groundQuad->collide(spheres[i]);
        /*if(spheres[i]->pos.Gety() <= -19.0)
        {
            spheres[i]->vPos.Sety(-0.75*(spheres[i]->vPos.Gety()));
            spheres[i]->pos.Sety(-19);
        }
        if(spheres[i]->pos.Gety() >= 19.0)
        {
            spheres[i]->vPos.Sety(-(spheres[i]->vPos.Gety()));
            spheres[i]->pos.Sety(19);
        }*/
        //bounding box, yo
        /*if(spheres[i]->pos.Getx() <= -20.0 )
        {
            spheres[i]->vPos.Setx(-0.75*(spheres[i]->vPos.Getx()));
            spheres[i]->pos.Setx(-19.5);
        }
        if(spheres[i]->pos.Getx() >= 20.0 )
        {
            spheres[i]->vPos.Setx(-0.75*(spheres[i]->vPos.Getx()));
            spheres[i]->pos.Setx(19.5);
        }
        if(spheres[i]->pos.Getz() <= -20.0)
        {
            spheres[i]->vPos.Setz(-0.75*(spheres[i]->vPos.Getz()));
            spheres[i]->pos.Setz(-19.5);
        }
        if(spheres[i]->pos.Getz() >= 20.0)
        {
            spheres[i]->vPos.Setz(-0.75*(spheres[i]->vPos.Getz()));
            spheres[i]->pos.Setz(19.5);
        }*/
    //}
    return True;
}


#ifdef linux
int main(int argc, char **argv)
{
    XEvent event;
    bool done;
    done = false;
    bool fs = false;
    daWindow = new Rust3D("Physics Test; Pavel Dmitriev 2103/2",800, 600, 24,  false);
    cam = new Camera(Vertex3D(0,-10, -30.0f));
    cam->rot = Vertex3D(35,0,0);
    buildPyramid();
    while (!done)
    {
        /* handle the events in the queue */
        while (XPending(daWindow->getDisplay()) > 0)
        {
            XNextEvent(daWindow->getDisplay(), &event);
            switch (event.type)
            {
                case Expose:
	                if (event.xexpose.count != 0)
	                    break;
                    drawGLScene();
         	        break;
            case ConfigureNotify:
            /* call resizeGLScene only if our window-size changed */
                if ((event.xconfigure.width != daWindow->getWidth()) ||
                    (event.xconfigure.height != daWindow->getheight()))
                {
                        std::cout <<"Resize event\n";
                    daWindow->resizeGLScene(event.xconfigure.width,
                        event.xconfigure.height);
                }
                break;
            /* exit in case of a mouse button press */
            case ButtonPress:
                done = True;
                break;
            case KeyPress:
                if (XLookupKeysym(&event.xkey, 0) == XK_Escape)
                {
                    done = true;
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_Return)
                {
                    //for (int i = 0; i< 10; i++)
                    //{
                        //spheres[0]->vPos += Vertex3D(rand() % 2 - 1,rand() % 2 - 1,rand() % 2 - 1);
                    //}

                }
                if (XLookupKeysym(&event.xkey, 0) == XK_space)
                {
                    //for (int i = 0; i< 10; i++)
                    //{
                        spheres[0]->pos = Vertex3D(rand() % 15 - 5,rand() % 15 - 5,rand() % 15 - 5);
                        spheres[0]->vPos = Vertex3D(0,0,0);
                    //}

                }
                if (XLookupKeysym(&event.xkey, 0) == XK_w)
                {
                    cam->rot.Setx(cam->rot.Getx() - 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_s)
                {
                    cam->rot.Setx(cam->rot.Getx() + 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_Left)
                {
                    cam->pos.Setx(cam->pos.Getx() + 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_Right)
                {
                    cam->pos.Setx(cam->pos.Getx() +- 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_Up)
                {
                    cam->pos.Setz(cam->pos.Getz() + 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_Down)
                {
                    cam->pos.Setz(cam->pos.Getz() - 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_z)
                {
                    cam->pos.Sety(cam->pos.Gety() + 0.5);
                }
                if (XLookupKeysym(&event.xkey, 0) == XK_a)
                {
                    cam->pos.Sety(cam->pos.Gety() - 0.5);
                }
                if (XLookupKeysym(&event.xkey,0) == XK_F1)
                {
                    //killGLWindow();

                    fs = !fs;
                    daWindow->destroyWindow();
                    daWindow->createWindow(daWindow->getTitle(), daWindow->getWidth(), daWindow->getheight(), daWindow->getBits(), fs);
                }
                break;
            case ClientMessage:
                if (*XGetAtomName(daWindow->getDisplay(), event.xclient.message_type) ==
                    *"WM_PROTOCOLS")
                {
                    std::cout << "Exiting sanely...\n";
                    done = true;
                }
                break;
            default:
                break;
            }
        }
        drawGLScene();
    }
    //killGLWindow();
    return 0;
}
#endif
